// import Vue from 'vue';
// import { store } from '@/store';
/**
 * 判断是否对象
 * @returns {boolean}
 */
export const isObject = (args) => {
  return Object.prototype.toString.call(args) === '[object Object]';
};
/**
 * 判断是否函数
 * @returns {boolean}
 */
 export function isFunction (value) {
	return Object.prototype.toString.call(value) === '[object Function]';
}

/**
 * 睡眠函数
 * @param ms 等待时间，毫秒
 * @param {Function=} callback
 * @return {Number|Promise}
 */
 export const sleep = (ms = 0, callback = Function) => {
	if (isFunction(callback)) {
		return setTimeout(callback, ms);
	}
	return new Promise(resolve => {
		setTimeout(resolve, ms);
	});
};
/**
 * 判断是否数组
 * @returns {boolean}
 */
export const isArray =
  Array.isArray ||
  function (value) {
    return Object.prototype.toString.call(value) === '[object Array]';
  };

/**
 * 判断对象是否包含特定的自身（非继承）属性
 * @param item
 * @param key
 * @return {boolean}
 */
export const hasOwnProperty = (item, key) => Object.prototype.hasOwnProperty.call(item, key);

/**
 * 下载文件(通过新开窗口下载)
 * @param {string} fileUrl  文件地址
 * @param {string} fileName 文件名
 */
export const downloadFileByNewWindow = (fileUrl, fileName) => {
  // 新版浏览器支持download,添加属性
  const aDom = document.createElement('a');
  aDom.setAttribute('href', fileUrl);
  aDom.setAttribute('download', fileName);
  aDom.setAttribute('target', '_blank');
  aDom.setAttribute('display', 'none');
  document.body.appendChild(aDom);
  aDom.click();
  document.body.removeChild(aDom); // 下载完成移除元素
  window.URL.revokeObjectURL(fileUrl); // 释放掉blob对象
};

/**
 * 将base64转换为文件
 * @param base64     base64字符串
 * @param type       mime类型
 */
export const base64ToBlob = (base64, type) => {
  const arr = base64.split(',');
  const mime = arr[0].match(/:(.*?);/)[1] || type;
  // 去掉url的头，并转化为byte
  const bytes = window.atob(arr[1]);
  // 处理异常,将ascii码小于0的转换为大于0
  const ab = new ArrayBuffer(bytes.length);
  // 生成视图（直接针对内存）：8位无符号整数，长度1个字节
  const ia = new Uint8Array(ab);
  for (let i = 0; i < bytes.length; i++) {
    ia[i] = bytes.charCodeAt(i);
  }
  return new Blob([ab], { type: mime });
};
/**
 * 移除监听事件
 * @param target
 * @param eventName
 * @param fn
 */
export const removeEventHandler = (target, eventName, fn) => {
  if (target?.removeEventListener) {
    target.removeEventListener(eventName, fn);
  } else {
    target?.detachEvent('on' + eventName, fn);
  }
};
/**
 * 创建一个从 object 中选中的属性的对象。
 * @param obj
 * @param keys
 */
 export const pick = (obj, ...keys) => {
	if (keys.length === 1 && keys[0] instanceof Array) {
		keys = keys[0];
	}
	const result = {};
	for (const key of keys) {
		if (Object.prototype.hasOwnProperty.call(obj, key)) {
			result[key] = deepCopy(obj[key]);
		}
	}
	return result;
};
/**
 * 绑定监听事件
 * @param target
 * @param eventName
 * @param fn
 * @param removeEvent
 */
export const addEventHandler = (target, eventName, fn, removeEvent = false) => {
  if (removeEvent) {
    removeEventHandler(target, eventName, fn);
  }
  if (target?.addEventListener) {
    target.addEventListener(eventName, fn);
  } else {
    target?.attachEvent('on' + eventName, fn);
  }
};

/**
 * 科学计数法转数字字符串(即：转换为非科学计数法)
 * @param num
 * @param fractionDigits 有效位数
 * @return string 将数字按科学计数法格式返回
 */
export const toNonExponential = (num, fractionDigits) => {
  const m = Number(num)
    .toExponential()
    .match(/^[+-]?\d(?:\.(\d*))?[E|e]([+-]\d+)/);
  if (!m) return num;
  let mynumber:number= +m[2] 
  fractionDigits = Number(fractionDigits ?? Math.max(0, (m[1] || '').length - mynumber));
  if (fractionDigits > 20) return num;
  return Number(num).toFixed(fractionDigits);
};

/**
 * 非空判断
 * @param value
 * @return {boolean}
 */
export const isNoEmpty = (value) => !isEmpty(value);
/**
 * 数字转科学计数法
 * @param num
 * @param fractionDigits 小数点后保留的位数
 * @return string 将数字按科学计数法格式返回
 */
export const toExponential = (num, fractionDigits) => {
  if (Number(num) === 0) return '0';
  return Number(num).toExponential(fractionDigits);
};
/**
 * 对象深拷贝
 * @param {Object} obj
 * @returns {null|*}
 */
export const deepCopy = (obj) => {
  if (!obj) return null;
  let result;
  // 判断是否是简单数据类型
  if (typeof obj === 'object') {
    // 复杂数据类型
    result = obj.constructor === Array ? [] : {};
    for (const key in obj) {
      if (Object.prototype.hasOwnProperty.call(obj, key)) {
        result[key] = typeof obj[key] === 'object' ? deepCopy(obj[key]) : obj[key];
      }
    }
  } else {
    // 简单数据类型,直接赋值
    result = obj;
  }
  return result;
};
/**
 * 获取文件名
 * @param {String} str
 * @returns {string}
 */
export const basename = (str = '') => {
  if (!str) return '';
  let idx = str.lastIndexOf('/');
  idx = idx > -1 ? idx : str.lastIndexOf('\\');
  if (idx < 0) {
    return str;
  }
  return str.substring(idx + 1);
};
/**
 * 空函数
 */
export const noop = () => {};
/**
 * 清除用户登录数据
 */
export const clearUserData = () => {
  return null;
};
/**
 * 判断是否字符串
 * @returns {boolean}
 */
export const isString = (value) => typeof value === 'string';

/**
 * 判断是否数字
 * @returns {boolean}
 */
export const isNumber = (value) => typeof value === 'number' && !isNaN(value);

/**
/**
 * 判断是否字符串数字(纯数字)
 */
export const isNumberStr = (value) => /^[0-9]*$/.test(trim(value));
/**
 * 去除左右空格
 * @param {String} str
 * @return {String}
 */
export const trim = (str) => {
  if (!str || typeof str !== 'string') return str;
  return str.replace(/^\s+|\s+$/g, '');
};

/**
 * 空判断
 * @param value
 * @return {boolean}
 */
export const isEmpty = (value) => value === null || value === undefined || value === '';
/**
 * 空对象验证
 * @param obj
 * @param {Array<*>} whiteList  不包含属性(白名单)
 * @returns {boolean}
 */
export const isEmptyObject = (obj, whiteList: string[] = []) => {
  if (!obj) return true;
  if (typeof obj !== 'object') return true;
  for (const key in obj) {
    if (Object.prototype.hasOwnProperty.call(obj, key) && !whiteList.includes(key)) {
      return false;
    }
  }
  return true;
};

/**
 * 对象转换为url参数
 * @param {Object} data
 * @returns {string}
 */
export const toUrlString = (data) => {
  const result: string[] = [];
  for (const key in data) {
    const value = data[key];
    if (value.constructor === Array) {
      value.forEach((val) => result.push(encodeURIComponent(key) + '=' + encodeURIComponent(val)));
    } else {
      result.push(encodeURIComponent(key) + '=' + encodeURIComponent(value));
    }
  }
  return result.join('&');
};
/**
 * 随机生成数字
 *
 * 示例：生成长度为 12 的随机数：randomNumber(12)
 * 示例：生成 3~23 之间的随机数：randomNumber(3, 23)
 *
 * @param1 最小值 | 长度
 * @param2 最大值
 * @return int 生成后的数字
 */
export function randomNumber(...args) {
  // 生成 最小值 到 最大值 区间的随机数
  const random = (min, max) => {
    return Math.floor(Math.random() * (max - min + 1) + min);
  };
  if (args.length === 1) {
    const [length] = args;
    // 生成指定长度的随机数字，首位一定不是 0
    const nums = [...Array(length).keys()].map((i) => (i > 0 ? random(0, 9) : random(1, 9)));
    return parseInt(nums.join(''));
  } else if (args.length >= 2) {
    const [min, max] = args;
    return random(min, max);
  } else {
    return Number.NaN;
  }
}
/**
 * 随机生成字符串
 * @param {Number} length 字符串的长度
 * @param {String} [chats] chats 可选字符串区间（只会生成传入的字符串中的字符）
 * @return string 生成的字符串
 */
export function randomString(length, chats) {
  if (!length) length = 1;
  if (!chats) chats = '0123456789qwertyuioplkjhgfdsazxcvbnm';
  let str = '';
  for (let i = 0; i < length; i++) {
    const num = randomNumber(0, chats.length - 1);
    str += chats[num];
  }
  return str;
}

/**
 * Wrap a mutation as a vuex action.
 */
export function wrapMutationAsAction(mutation) {
  return ({ commit }, value) => commit(mutation, value);
}

/**
 * A wrapper function for pxm.createRepresentationInAllViews that
 * correctly manages which representation is bound to 2D manipulators.
 */
export function createRepresentationInAllViews(pxm, source) {
  const views2D = pxm.getViews().filter((v) => v.isA('vtkView2DProxy'));
  // reach in to get sliceRepresentation, since it's not default exposed
  const origReps = views2D.map((v) => v.getReferenceByName('sliceRepresentation'));

  pxm.createRepresentationInAllViews(source);

  // do not focus labelmaps
  if (source.getProxyName() === 'LabelMap') {
    views2D.forEach((view, i) => view.bindRepresentationToManipulator(origReps[i]));
  }
}

export function makeSubManager() {
  let currentSub = null;

  const api = {
    sub(subscription) {
      api.unsub();
      currentSub = subscription;
    },
    unsub() {
      if (currentSub !== null) {
        //@ts-ignore
        currentSub.unsubscribe();
        currentSub = null;
      }
    },
  };

  return api;
}
